#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2017/5/2 下午6:08
# @Author  : zhangzhen
# @Site    : 
# @File    : svm_demo.py
# @Software: PyCharm
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm

def demo1():
    # we create 40 separable points
    rng = np.random.RandomState(0)
    n_samples_1 = 1000
    n_samples_2 = 100
    X = np.r_[1.5 * rng.randn(n_samples_1, 2),
              0.5 * rng.randn(n_samples_2, 2) + [2, 2]]
    y = [0] * (n_samples_1) + [1] * (n_samples_2)
    print X
    print y
    print 100 * '-'

    # fit the model and get the separating hyperplane
    clf = svm.SVC(kernel='linear', C=1.0)
    clf.fit(X, y)

    w = clf.coef_[0]
    a = -w[0] / w[1]
    xx = np.linspace(-5, 5)
    yy = a * xx - clf.intercept_[0] / w[1]

    # get the separating hyperplane using weighted classes
    wclf = svm.SVC(kernel='linear', class_weight={1: 10})
    wclf.fit(X, y)

    ww = wclf.coef_[0]
    wa = -ww[0] / ww[1]
    wyy = wa * xx - wclf.intercept_[0] / ww[1]

    # plot separating hyperplanes and samples
    h0 = plt.plot(xx, yy, 'k-', label='no weights')
    h1 = plt.plot(xx, wyy, 'k--', label='with weights')
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
    plt.legend()

    plt.axis('tight')
    plt.show()


def svc():
    """
    SVC（C-Support Vector Classification）
    支持向量分类，基于libsvm实现的,
    数据拟合的时间复杂度是数据样本的二次方,这使得他很难扩展到10000个数据集
    [支持多分类]
    
    SVC参数解释
    （1）C: 目标函数的惩罚系数C，用来平衡分类间隔margin和错分样本的，default C = 1.0； 
    （2）kernel：参数选择有RBF, Linear, Poly, Sigmoid, 默认的是"RBF"; 
    （3）degree：if you choose 'Poly' in param 2, this is effective, degree决定了多项式的最高次幂； 
    （4）gamma：核函数的系数('Poly', 'RBF' and 'Sigmoid'), 默认是gamma = 1 / n_features; 
    （5）coef0：核函数中的独立项，'RBF' and 'Poly'有效； 
    （6）probablity: 可能性估计是否使用(true or false)； 
    （7）shrinking：是否进行启发式； 
    （8）tol（default = 1e - 3）: svm结束标准的精度; 
    （9）cache_size: 制定训练所需要的内存（以MB为单位）； 
    （10）class_weight: 每个类所占据的权重，不同的类设置不同的惩罚参数C, 缺省的话自适应； 
    （11）verbose: 跟多线程有关，不大明白啥意思具体； 
    （12）max_iter: 最大迭代次数，default = 1， if max_iter = -1, no limited; 
    （13）decision_function_shape ： ‘ovo’ 一对一, ‘ovr’ 多对多  or None 无, default=None 
    （14）random_state ：用于概率估计的数据重排时的伪随机数生成器的种子。 
     ps：7,8,9一般不考虑。 
    :return: 
    """
    X = np.array([[-1, -1], [-2, -1], [1, 1], [2, 1]])
    y = np.array([1, 1, 2, 2])

    clf = svm.SVC()
    clf.fit(X, y)
    print clf.fit(X, y)
    print clf.predict([[-0.8, -1]])
    pass


def nu_svc():
    """
    核支持向量分类,和SVC类似,也是基于libsvm实现的,
    但不同的是通过一个参数控制支持向量的个数
    :return: 
    """
    X = np.array([[-1, -1], [-2, -1], [1, 1], [2, 1]])
    y = np.array([1, 1, 2, 2])
    clf = svm.NuSVC()
    clf.fit(X, y)
    print clf.fit(X, y)
    print(clf.predict([[-0.8, -1]]))
    pass


def linear_svc():
    """
    LinearSVC 参数解释  
    C：目标函数的惩罚系数C，用来平衡分类间隔margin和错分样本的，default C = 1.0；  
    loss:指定损失函数  
    penalty: 
    dual:选择算法来解决对偶或原始优化问题。当n_samples > n_features 时dual=false。  
    tol:(default = 1e - 3):svm结束标准的精度;
    multi_class：如果y输出类别包含多类，用来确定多类策略,ovr表示一对多,“crammer_singer”优化所有类别的一个共同的目标  
    如果选择“crammer_singer”,损失、惩罚和优化将会被被忽略。  
    fit_intercept:  
    intercept_scaling:
    class_weight:对于每一个类别i设置惩罚系数C = class_weight[i]*C,如果不给出,权重自动调整为 n_samples / (n_classes * np.bincount(y))  
    verbose:跟多线程有关，不大明白啥意思具体
    """
    X = [[0], [1], [2], [3]]
    Y = [0, 1, 2, 3]

    # clf = svm.SVC(decision_function_shape='ovo')  #
    clf = svm.SVC()
    clf.fit(X, Y)
    print clf.fit(X, Y)

    dec = clf.decision_function([[1]])  # 返回的是样本距离超平面的距离
    print dec

    clf.decision_function_shape = "ovr"
    dec = clf.decision_function([1])  # 返回的是样本距离超平面的距离
    print dec

    # 预测
    print clf.predict([1])

    pass
if __name__ == '__main__':

    # svc()
    # nu_svc()
    linear_svc()
    pass